/*
 * Copyright (c) 2009 Johnny Mast
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#import "HieroBitmapFont.h"

@interface HieroBitmapFont (Private)
-(void)parseFontFile:(NSString*)fontname;
-(void)createSpaceTexture;
-(Image*)getImageForCharacter:(NSInteger)character;
-(NSMutableArray*)getImagesForString:(NSString*)text;
@end


@implementation HieroBitmapFont
@synthesize fontinformation;
@synthesize cachedImages;
@synthesize charHeight;
@synthesize charWidth;
@synthesize charSpacing;
@synthesize charScale;
@synthesize fontSheet;
@synthesize fontimage;
@synthesize blinker;
@synthesize _blinksheet;

-(void) dealloc
{
	[_blinksheet release];
	[[Resources SharedResourceManager] releaseTextureWithName:spaceTextureName];
	[cachedImages release];
	[fontinformation release];
	[super dealloc];
}


-(id)initWithFontName:(NSString*)fontname filter:(GLenum)aFilter scale:(float)scale {
	
	fontimage = [NSString stringWithFormat:@"%@.png", fontname];
	fontSheet = [(Image *)[Image alloc] initWithImage:fontimage filter:GL_NEAREST]; 
	
	NSString* fontimagefilename = [[NSBundle mainBundle] pathForResource:fontname ofType:@"png"];
	_blinksheet       = [[UIImage imageWithContentsOfFile:fontimagefilename] retain];
	
	if (!fontimage)
	{
#if defined(GAMENGINE_DEBUG)
		NSLog(@"HieroBitmapFont: Error, could not find the font image.");
#endif
	} 
	
	
	[self createSpaceTexture];
	
	[self setWidth:16];
	[self setHeight:16];
	[self setSpacing:scale];
	[self setScale:scale];
	[self parseFontFile:fontname];
	return self;
}


-(void)renderTextAtPoint:(CGPoint)point text:(NSString*)text {
	NSMutableArray *images = [self getImagesForString:text];
	
	for(int i = 0; i < [images count]; i++)
	{
		[[images objectAtIndex:i] renderAtPoint:point centerOfImage:NO];
		int width = [[images objectAtIndex:i] imageWidth];
		point.x  += width+ charSpacing;
	}
}



-(void)blinkTextAtPoint:(CGPoint)point text:(NSString*)text {
	
	
	NSInteger contextWidth = 0;
	NSInteger contextHeight = 0;
	
	if (!blinker) /* First run */
	{
		
		
		for(int i = 0; i < [text length]; i++)
		{
			NSString*  charIDString = [NSString stringWithFormat:@"%d", [text characterAtIndex:i]];
			
			if ([fontinformation objectForKey:charIDString])
			{
				NSInteger width = [[[fontinformation objectForKey:charIDString] objectForKey:@"width"] intValue];
				NSInteger height = [[[fontinformation objectForKey:charIDString] objectForKey:@"height"] intValue];
				NSInteger xadvance = [[[fontinformation objectForKey:charIDString] objectForKey:@"xadvance"] floatValue];
				
				contextWidth  += (width + xadvance);
				contextHeight += height;
			}
		}
		
		CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
		CGContextRef context = CGBitmapContextCreate(NULL, contextWidth, contextHeight, 8,4 * contextWidth, colorSpace, kCGImageAlphaPremultipliedFirst);
		CGColorSpaceRelease(colorSpace);
		
		float lastX = 0;
		
		for(int i = 0; i < [text length]; i++)
		{
			NSInteger  characterID  = [text characterAtIndex:i];
			NSString*  charIDString = [NSString stringWithFormat:@"%d", characterID];
			NSString*  charAsString = [NSString stringWithFormat:@"%c", characterID];
			
			if ([fontinformation objectForKey:charIDString])
			{
				NSLog(@"Creating image for %@", charAsString);
				float width = [[[fontinformation objectForKey:charIDString] objectForKey:@"width"] floatValue];
				float height = [[[fontinformation objectForKey:charIDString] objectForKey:@"height"] floatValue];
				float xadvance = [[[fontinformation objectForKey:charIDString] objectForKey:@"xadvance"] floatValue];
				float x        = [[[fontinformation objectForKey:charIDString] objectForKey:@"x"] floatValue];  
				float y        = [[[fontinformation objectForKey:charIDString] objectForKey:@"y"] floatValue];  
				
				CGImageRef copy;
				
				if (characterID == 32)
				{
					/*
					 ** Fist of all since this is a font system we need to have a " " (space) image aswell
					 ** so se have a shared resources class that could help us out with that so lets create 
					 ** that texture first.
					 */
					CGContextRef spacecontext = CGBitmapContextCreate(NULL, 
																	  spaceWidth, // width
																	  spaceHeight, // height 
																	  8,
																	  4 * spaceHeight,  
																	  colorSpace, 
																	  kCGImageAlphaPremultipliedFirst);
					
					copy = CGBitmapContextCreateImage(context);
					CGContextRelease(spacecontext);
				} else {
					copy = CGImageCreateWithImageInRect([_blinksheet CGImage], CGRectMake(x, 
																						  y, 
																						  width, 
																						  height));
					
				}
				if (copy) {
					CGContextDrawImage(context, CGRectMake(lastX,
														   0, 
														   width, 
														   height), 
									   copy);
					
					CFRelease(copy);
				}
				lastX += width + xadvance;
			}
		}
		
		[[Resources SharedResourceManager] increaseActiveblinkers];
		
		
		UIImage* newImage   = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
		NSInteger activeBlinkers = [[Resources SharedResourceManager] activeblinkers];
		NSString *textureName    = [NSString stringWithFormat:@"_blinkerResource_%d", activeBlinkers];
		
		
		
		
		
		[[Resources SharedResourceManager] setTextureImageWithName:textureName
													  textureImage:newImage];	
		
		Image* blinkerimage = [[(Image *)[Image alloc] initWithImage:textureName] autorelease];
		[blinkerimage setScale:charScale];
		
		blinker = [(Blink *)[Blink alloc] initWithImage:blinkerimage];
		
		CGContextRelease(context);
		UIGraphicsEndImageContext();
		
		[blinker renderAtPoint:point centerOfImage:NO];
	} else {
		[blinker renderAtPoint:point centerOfImage:NO];
	}
}

-(void)updateBlinkWithDelta:(float)delta {
	
	[blinker update: delta];
}

-(void)setHeight:(float)height {
	charHeight = height;	
}

-(void)setWidth:(float)width {
	charWidth = width;
}

-(void)setSpacing:(float)spacing {
	charSpacing = spacing;	
}

-(void)setScale:(float)scale {
	charScale = scale;
}
@end


@implementation HieroBitmapFont (Private)

-(void)parseFontFile:(NSString*)fontname {
	
	NSString* filename = [[NSBundle mainBundle] pathForResource:fontname ofType:@"fnt"];
	
	if(![[NSFileManager defaultManager] fileExistsAtPath:filename])
	{
#if defined(GAMENGINE_DEBUG)
		NSLog(@"HieroBitmapFont: Error, Could not find font file");
#endif
	}
	
	NSData*   fontloader  = [NSData dataWithContentsOfFile:filename];
	NSString* filecontent =  [[NSString alloc] initWithData:fontloader encoding:NSUTF8StringEncoding];	
	NSArray * lines       = [[NSArray alloc] initWithArray:[filecontent componentsSeparatedByString:@"\n"]];
	
	fontinformation = [[NSMutableDictionary alloc] init];
	cachedImages    = [[NSMutableDictionary alloc] init];
	
	NSMutableArray* characters = [[NSMutableArray alloc] init];
	
	for(int i = 0; i < [lines count]; i++)
	{
		if ([[lines objectAtIndex:i] hasPrefix:@"char id"])
		{
			NSMutableDictionary* information = [[NSMutableDictionary alloc] init];
			NSString* line = [lines objectAtIndex:i];
			
			line = [line stringByReplacingOccurrencesOfString:@" " withString:@"|"];
			NSArray* values = [line componentsSeparatedByString:@"|"];
			
			for(int j = 0; j < [values count]; j++)
			{
				if ([[values objectAtIndex:j] length] > 0)
				{
					NSArray* _info = [[values objectAtIndex:j] componentsSeparatedByString:@"="];
					
					if ([_info count] == 2) {
						[information setObject:[_info objectAtIndex:1] forKey:[_info objectAtIndex:0]]; 
					}
				}
				
			}
			[fontinformation setObject:information forKey:[information objectForKey:@"id"]];			
			[characters addObject:[information objectForKey:@"id"]];
			
			[information release];
		}
		
	}
	
	// Set image height and width for a space
	NSMutableDictionary* spaceimginfo = [fontinformation objectForKey:@"32"]; /* 32 == ascii for space */
	
	[spaceimginfo setValue:[NSString stringWithFormat:@"%f", spaceWidth] forKey:@"width"];
	[spaceimginfo setValue:[NSString stringWithFormat:@"%f", spaceHeight] forKey:@"height"];
	
	[fontinformation setValue:spaceimginfo forKey:@"32"];
	
	for(int i = 0; i < [characters count]; i++)
	{
		NSInteger charid = [[characters objectAtIndex:i] intValue];
		Image* tmp = [self getImageForCharacter:charid];
		
		if (tmp)
			[cachedImages setObject:tmp
							 forKey:[NSString stringWithFormat:@"%c", charid]];
		
		
	}
	[characters release];
	[lines release];
	[filecontent release];
}

-(NSMutableArray*)getImagesForString:(NSString*)text {
	
	NSMutableArray *images = [[NSMutableArray alloc] init];
	
	for(int i = 0; i < [text length]; i++)
	{
		NSInteger character = [text characterAtIndex:i];
		
		if ([cachedImages objectForKey:[NSString stringWithFormat:@"%c", character]])
		{
			Image *charimg =  [cachedImages objectForKey:[NSString stringWithFormat:@"%c",character]];
			
			[images addObject:charimg];
		} else {
#if defined(GAMENGINE_DEBUG)
			NSLog(@"HieroBitmapFont: (getImagesForString) No deffenition found for char number %d (\"%c\")", character, character);
#endif
		}
	}
	return [images retain];
}

-(void) createSpaceTexture {
	/*
	 ** Fist of all since this is a font system we need to have a " " (space) image aswell
	 ** so se have a shared resources class that could help us out with that so lets create 
	 ** that texture first.
	 */
	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
	CGContextRef context = CGBitmapContextCreate(NULL, 
												 spaceWidth, // width
												 spaceHeight, // height 
												 8,
												 4 * spaceHeight,  
												 colorSpace, 
												 kCGImageAlphaPremultipliedFirst);
	CGColorSpaceRelease(colorSpace);
	UIImage *textureImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
	CGContextRelease(context);
	UIGraphicsEndImageContext();
	[[Resources SharedResourceManager] setTextureImageWithName:spaceTextureName
												  textureImage:textureImage];	
}

-(Image*)getImageForCharacter:(NSInteger)character
{	
	if ([fontinformation objectForKey:[NSString stringWithFormat:@"%d",character]])
	{
		NSMutableDictionary* _info = [fontinformation objectForKey:[NSString stringWithFormat:@"%d", character]];
		
		
		if (character == 32) /* Space */
		{
			return [[(Image *)[Image alloc] initWithImage:spaceTextureName] autorelease];
		}
		else {
			
			GLuint width  = [[_info objectForKey:@"width"] floatValue];
			GLuint height = [[_info objectForKey:@"height"] floatValue];
			GLuint x      = [[_info objectForKey:@"x"] floatValue];
			GLuint y      = [[_info objectForKey:@"y"] floatValue];
			
			Image* theChar = [fontSheet getSubImageAtPoint:CGPointMake(x,y) 
											 subImageWidth:width
											subImageHeight:height
													 scale:charScale];
			[theChar setImageWidth:width];
			[theChar setImageHeight:height];
			
			return theChar;
		}
		
	} else {
#if defined(GAMENGINE_DEBUG)
		NSLog(@"HieroBitmapFont: (getImageForCharacter) No deffenition found for char number %d (\"%c\")", character,  character);
#endif
	}
	return nil;
}



@end